package mybatis.executor;

import mybatis.mapper.MapperStatement;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author cg
 * @date 2023/6/20 14:07
 * 解析mapper对象
 */
public class StatementHandler {
    private MapperStatement mapperStatement;

    public StatementHandler(MapperStatement mapperStatement) {
        this.mapperStatement = mapperStatement;
    }

    /**
     * 将mapper中的sql语句解析为sql的预处理语句
     *
     * @param connection
     * @return
     */
    public PreparedStatement resolve(Connection connection, Map<String, Object> parameters) {
        try {
            String sql = mapperStatement.getSql().trim();
            //将${}拼接到sql语句中
            Pattern pattern = Pattern.compile("\\$\\{(.+?)}");
            Matcher matcher = pattern.matcher(sql);
            StringBuffer sb = new StringBuffer();
            while (matcher.find()) {
                String parameterName = matcher.group(1);
                Object replacement = parameters.get(parameterName);
                matcher.appendReplacement(sb, replacement.toString());
            }
            matcher.appendTail(sb);
            sql = sb.toString();
            //将#{}替换为?
            pattern = Pattern.compile("#\\{(.+?)}");
            matcher = pattern.matcher(sql);
            while (matcher.find()) {
                sql = matcher.replaceAll("?");
            }

            return connection.prepareStatement(sql);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 将？填充为对应的参数
     *
     * @param preparedStatement
     * @param parameters
     */
    public void injectParameters(PreparedStatement preparedStatement, Map<String, Object> parameters) {
        int idx = 0;
        for (String statementParameter : mapperStatement.getParameters()) {
            try {
                //替换statementParameter中的占位符参数
                preparedStatement.setObject(++idx, parameters.get(statementParameter));
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
